﻿using System.Drawing;
using System.Runtime.Serialization;

namespace K3R.Imaging {
	public enum RectangleType {
		Scale, Zoom, Fill
	}

	[DataContract]
	public class Dimensions {
		private const bool c_centre = true;

		[DataMember(Name = "frameHeight")] public int FrameHeight { get; set; }
		[DataMember(Name = "frameWidth")] public int FrameWidth { get; set; }
		[DataMember(Name = "imageHeight")] public int ImageHeight { get; set; }
		[DataMember(Name = "imageWidth")] public int ImageWidth { get; set; }

		#region Instance
		public Rectangle ScaleRectangle(bool centre) {
			return Dimensions.ScaleRectangle(FrameHeight, FrameWidth, ImageHeight, ImageWidth, centre);
		}

		public Rectangle ScaleRectangle() {
			return ScaleRectangle(c_centre);
		}

		public Rectangle ZoomRectangle(bool centre) {
			return Dimensions.ZoomRectangle(FrameHeight, FrameWidth, ImageHeight, ImageWidth, centre);
		}

		public Rectangle ZoomRectangle() {
			return ZoomRectangle(c_centre);
		}

		public Rectangle FillRectangle(bool centre) {
			return Dimensions.FillRectangle(FrameHeight, FrameWidth, ImageHeight, ImageWidth, centre);
		}

		public Rectangle FillRectangle() {
			return FillRectangle(c_centre);
		}

		public Rectangle CreateRectangle(RectangleType type, bool centre) {
			return Dimensions.CreateRectangle(type, FrameHeight, FrameWidth, ImageHeight, ImageWidth, centre);
		}

		public Rectangle CreateRectangle(RectangleType type) {
			return CreateRectangle(type, c_centre);
		}
		#endregion

		#region Static
		public static Rectangle ScaleRectangle(int frameHeight, int frameWidth, int imageHeight, int imageWidth, bool centre) {
			int x = 0, y = 0, height, width;

			if (imageHeight > frameHeight || imageWidth > frameWidth) {
				decimal heightDifference = (decimal)frameHeight / (decimal)imageHeight;
				decimal widthDifference = (decimal)frameWidth / (decimal)imageWidth;

				if (widthDifference > heightDifference) {
					width = (int)(heightDifference * imageWidth);
					height = frameHeight;
				}
				else {
					width = frameWidth;
					height = (int)(widthDifference * imageHeight);
				}
			}
			else {
				height = imageHeight;
				width = imageWidth;
			}

			if (centre) {
				x = (frameWidth / 2) - (width / 2);
				y = (frameHeight / 2) - (height / 2);
			}

			return new Rectangle(x, y, width, height);
		}

		public static Rectangle ZoomRectangle(int frameHeight, int frameWidth, int imageHeight, int imageWidth, bool centre) {
			int x = 0, y = 0, height, width;

			decimal frameRatio = (decimal)frameWidth / (decimal)frameHeight;
			decimal actualRatio = (decimal)imageWidth / imageHeight;

			if (frameRatio == actualRatio) { //Equal
				height = frameHeight;
				width = frameWidth;
			}
			else if (frameRatio < actualRatio) { //Too Long
				width = (int)((decimal)frameHeight * actualRatio);
				height = frameHeight;
			}
			else { //Too Short
				height = (int)((decimal)frameWidth / actualRatio);
				width = frameWidth;
			}

			if (centre) {
				x = (frameWidth / 2) - (width / 2);
				y = (frameHeight / 2) - (height / 2);
			}

			return new Rectangle(x, y, width, height);
		}

		public static Rectangle OldFillRectangle(int frameHeight, int frameWidth, int imageHeight, int imageWidth, bool centre) {
			int x = 0, y = 0, height, width;

			if (imageHeight != frameHeight || imageWidth != frameWidth) {
				if (imageHeight > imageWidth) {
					height = (int)(imageHeight * ((decimal)frameWidth / imageWidth));
					width = frameWidth;
				}
				else {
					width = (int)(imageWidth * ((decimal)frameHeight / imageHeight));
					height = frameHeight;
				}
			}
			else {
				height = imageHeight;
				width = imageWidth;
			}

			if (centre) {
				x = (frameWidth / 2) - (width / 2);
				y = (frameHeight / 2) - (height / 2);
			}

			return new Rectangle(x, y, width, height);
		}

		public static Rectangle FillRectangle(int frameHeight, int frameWidth, int imageHeight, int imageWidth, bool centre) {
			int x = 0, y = 0, height, width;

			if (imageHeight != frameHeight || imageWidth != frameWidth) {
				if (imageHeight > imageWidth) {
					height = frameHeight;
					width = (int)(imageWidth * ((decimal)frameHeight / imageHeight));
				}
				else {
					width = frameWidth;
					height = (int)(imageHeight * ((decimal)frameWidth / imageWidth));
				}
			}
			else {
				height = imageHeight;
				width = imageWidth;
			}

			if (centre) {
				x = (frameWidth / 2) - (width / 2);
				y = (frameHeight / 2) - (height / 2);
			}

			return new Rectangle(x, y, width, height);
		}

		public static Rectangle CreateRectangle(RectangleType type, int frameHeight, int frameWidth, int imageHeight, int imageWidth, bool centre) {
			switch (type) {
				case RectangleType.Scale:
					return ScaleRectangle(frameHeight, frameWidth, imageHeight, imageWidth, centre);
				case RectangleType.Zoom:
					return ZoomRectangle(frameHeight, frameWidth, imageHeight, imageWidth, centre);
				default: // Fill
					return FillRectangle(frameHeight, frameWidth, imageHeight, imageWidth, centre);
			}
		}
		#endregion
	}
}
